#!/bin/bash
# Onion services manager
# acetone at mail.i2p
# 2022

TORRC="/etc/tor/torrc"
TORDIR="/var/lib/tor"

###############################
###############################
######################### funcs

tor_install() {
    apt update
    apt install tor -y
    systemctl restart tor
    systemctl enable tor
}

tor_restart() {
    systemctl restart tor
    counter=0
    if [[ $? != 0 ]]; then
        let counter++
        echo "Tor service restarting failed, retrying ($counter)"
        sleep 3
        tor_restart
    fi;
}

service_del() {
    if [[ "$(cat $TORRC | grep "### BEGIN $1 ###")" == "" ]]; then
        echo -e "Service '$1' not existed"
        exit 1
    fi
    sed "/### BEGIN $1 ###/,$ d" $TORRC > /tmp/onionsman_tmp_1
    sed "1,/### END $1 ###/ d" $TORRC > /tmp/onionsman_tmp_2
    cat /tmp/onionsman_tmp_1 > $TORRC
    cat /tmp/onionsman_tmp_2 >> $TORRC
    tor_restart
    
    echo "Deleted: $1"
}

service_create() {
    if [[ "$(cat $TORRC | grep "### BEGIN $1 ###")" != "" ]]; then
        echo "'$1' looks like already existed. Use another name."
        exit 1
    fi
    
    echo -e "### BEGIN $1 ###" >> $TORRC
    echo -e "HiddenServiceDir $TORDIR/$1/" >> $TORRC
    echo -e "HiddenServicePort $2 $3" >> $TORRC
    echo -e "### END $1 ###" >> $TORRC
    
    tor_restart
    sleep 2
    address=$(cat $TORDIR/$1/hostname)
    if [[ address == "" ]]; then
        echo -e "Service creating failed..."
        exit 1
    fi
    
    echo -e "Service created! Address:\n$address"
}

service_print() {
    address=$(cat $TORDIR/$1/hostname)
    if [[ $? != 0 ]]; then
        echo -e "Service not existed or invalid"
        echo -e "Check it manually: $TORDIR/$1/hostname"
        exit 1
    fi
    echo $address
}

service_list() {
    all=($(cat $TORRC | grep "### BEGIN" | cut -f3 -d' ' | cut -f1 -d' '))
    enabled=($(cat $TORRC | grep "^### BEGIN" | cut -f3 -d' ' | cut -f1 -d' '))
    disabled=($(cat $TORRC | grep "#### BEGIN" | cut -f3 -d' ' | cut -f1 -d' '))
    
    echo -e "All: ${#all[@]}"
    if [[ ${enabled[@]} > 0 ]]; then
        echo -e "  Enabled (${#enabled[@]}):"
        for j in "${!enabled[@]}"
        do
            name=${enabled[j]}
            echo -e "    [$name] $(sed -n "/### BEGIN $name ###/,+2p" $TORRC | tail -n 1 | cut -f2,3 -d' ')"
        done
    fi
    
    if [[ ${disabled[@]} > 0 ]]; then
        echo -e "  Disabled (${#disabled[@]}):"
        for i in "${!disabled[@]}"
        do
            name=${disabled[i]}
            echo -e "    [$name] $(sed -n "/### BEGIN $name ###/,+2p" $TORRC | tail -n 1 | cut -f2,3 -d' ')"
        done
    fi   
}

service_stop() {
    if [[ "$(cat $TORRC | grep "#### BEGIN $1 ###")" != "" ]]; then
        echo "Can not disable '$1': already stopped"
        exit 1
    fi
    
    if [[ "$(cat $TORRC | grep "### BEGIN $1 ###")" == "" ]]; then
        echo "Can not disable '$1': service not exist"
        exit 1
    fi
    
    str1=$(sed -n "/### BEGIN $1 ###/,+2p" $TORRC | tail -n 2 | head -n 1)
    str2=$(sed -n "/### BEGIN $1 ###/,+2p" $TORRC | tail -n 1)
    
    begin=$(sed -n "/^### BEGIN $1 ###/=" $TORRC)
    
    for ((i=begin; begin<i+4; begin++)); do
        sed -i "${begin}s/^/#/" $TORRC
    done
    
    tor_restart
    
    echo -e "\033[1m-\033[0m\t$str1"
    echo -e "\033[1m-\033[0m\t$str2"
}

service_start() {
    if [[ "$(cat $TORRC | grep "### BEGIN $1 ###")" == "" ]]; then
        echo "Can not start '$1': not exist"
        exit 1
    fi
    
    if [[ "$(cat $TORRC | grep "#### BEGIN $1 ###")" == "" ]]; then
        echo "Can not start '$1': already enabled"
        exit 1
    fi
  
    begin=$(sed -n "/^#### BEGIN $1 ###/=" $TORRC)
    
    for ((i=begin; begin<i+4; begin++)); do
        sed -i "${begin}s/^#//" $TORRC
    done
    
    str1=$(sed -n "/### BEGIN $1 ###/,+2p" $TORRC | tail -n 2 | head -n 1)
    str2=$(sed -n "/### BEGIN $1 ###/,+2p" $TORRC | tail -n 1)
    
    tor_restart
    
    echo -e "\033[1m+\033[0m\t$str1"
    echo -e "\033[1m+\033[0m\t$str2"
}

service_status() {
    if [[ "$(cat $TORRC | grep "#### BEGIN $1 ###")" != "" ]]; then
        echo "'$1' is disabled"
        else if [[ "$(cat $TORRC | grep "### BEGIN $1 ###")" != "" ]]; then
            echo "'$1' is enabled"
        else
            echo "Error: '$1' not exist"
        fi
    fi
}

###############################
###############################
######################### calls

if [[ $1 == "help" ]]; then
    echo -e "Usage:"
    echo -e "\033[1mcreate\033[0m <name> <tor port> <address>     example: create testservice 80 127.0.0.1:8080"
    echo -e "\033[1mremove\033[0m <name>                          example: remove testservice"
    echo -e "\033[1mlist\033[0m                                   print name list of existed services"
    echo -e "\033[1mprint\033[0m <name>                           print onion address for passed name"
    echo -e "\033[1mstop\033[0m <name>                            disable active hidden service"
    echo -e "\033[1mstart\033[0m <name>                           enable disabled hidden service"
    echo -e "\033[1mstatus\033[0m <name>                          print status of hidden service (off/on)"
    echo -e "\nonionsman: Onion services manager"
    exit 0
fi

if [ "$EUID" -ne 0 ]
  then echo "Please run as root"
  exit
fi

if [[ $1 == "install" ]]; then
    tor_install
    exit 0
fi

if [[ $1 == "restart" ]]; then
    tor_restart
    exit 0
fi

systemctl status tor &> /dev/null
if [[ $? != "0" ]]; then
    echo "TOR seems not installed. Use \"install\" or \"restart\" parameter."
    exit 1
fi

if [[ $1 == "create" ]]; then
    service_create $2 $3 $4
    exit 0
fi

if [[ $1 == "remove" ]]; then
    service_del $2
    exit 0
fi

if [[ $1 == "print" ]]; then
    service_print $2
    exit 0
fi

if [[ $1 == "list" ]]; then
    service_list
    exit 0
fi

if [[ $1 == "stop" ]]; then
    service_stop $2
    exit 0
fi

if [[ $1 == "start" ]]; then
    service_start $2
    exit 0
fi

if [[ $1 == "status" ]]; then
    service_status $2
    exit 0
fi

echo "No known arguments. Use 'help'"
exit 1
